<?php
/**
 * @class Container
 * 实现依赖注入的主要部分
 */
namespace Mkd\Container;

use Symfony\Component\Yaml\Yaml;

class Container
{
	private $services_list;
	private $config_files;
	public function __construct()
	{
		$this->service_list = [];
		$this->config_files = [];
		$this->parseConfig();
	}

	public function parseConfig()
	{
		$app_config_path = ROOT."/app/config/service.yml";
		if (!file_exists($app_config_path)) {
			throw new \Exception("The service configuration file should be locate in {$app_config_path} dose not exists");
		}
		$configs = Yaml::parse(file_get_contents($app_config_path));
		foreach ($configs as $config) {
			$resource = $config['resource'];
			$resource = ltrim($resource, "@");
			$file = ROOT."/src/{$resource}/Resources/service.yml";
			if (!file_exists($file))
				continue;
			$this->config_files[$resource] = $file;
		}
		foreach ($this->config_files as $config_file) {
			$config = Yaml::parse(file_get_contents($config_file));
			foreach ($config as $key => $value) {
				$this->services_list[$key] = $value;
				$this->services_list[$key]['instance'] = null;
			}
		}
	}

	/**
	 * @param $service
	 * @return class
	 * 获得service
	 */
	public function get($key)
	{
		$service = $this->services_list[$key];
		if ($service['instance'] == null) {
			$service['instance'] = $this->createInstance($key);
		}
	
		$this->services_list[$key] = $service;
		return $service['instance'];
	}

	/**
	 * @param $service
	 * @param $instance
	 * 修改service
	 */
	public function set($key, $instace)
	{
		if ($instace instanceof $this->services_list[$key]['map']) {
			$this->services_list[$key]['instance'] = $instace;
			return true;
		}
		return false;
	}
	/**
	 * @param $key
	 * @return $key['instance']
	 * 创建一个注入的实例
	 */
	public function createInstance($key)
	{
		$service = $this->services_list[$key];
		$class_file = ROOT.'/src/'.$service['map'].".php";
		$class_file = str_replace("\\", "/", $class_file);
		if (!file_exists($class_file) || !class_exists($service['map'])) {
			throw new \Exception("The map class <b>{$service['map']}</b> of service <b>$key</b> dose not exists");
		}
		foreach ($service['parameters'] as $k =>$p) {
	
			if ($p[0] === "@") {
				$p = $this->get(substr($p, 1, strlen($p)));
				$service['parameters'][$k] = $p;
			}
		}
		$reflectionClass = new \ReflectionClass($service['map']);
	
		$service['instance'] = $reflectionClass->newInstanceArgs($service['parameters']);
		$this->services_list[$key] = $service;
		return $service['instance'];
	}
}
?>
